package com.mspbots.sync.wise.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.mspbots.api.DataNotFoundException;
import com.mspbots.sync.BaseGenericService;
import com.mspbots.sync.model.ExceptionLog;
import com.mspbots.sync.model.TimeEntry;
import com.mspbots.sync.utils.WiseParamsUtils;
import com.mspbots.sync.utils.WiseResultBuildUtils;
import com.mspbots.sync.wise.client.ClientProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.time.format.DateTimeFormatter;
import java.util.Map;

/**
 * com.mspbots.sync.scheduled.service.TimeEnTriesService
 *
 * @author Alex bob(https://github.com/vnobo)
 * @date Created by 2019/6/10
 */
@Log4j2
@Service
@RequiredArgsConstructor
public class TimeEntriesService extends BaseGenericService {

    public Mono<JsonNode> getPage(Map<String, String> queryParams) {
        Integer tenant = Integer.parseInt(queryParams.get("tenantId"));
        log.debug("This tenant {} get sync connect wise Time Entry.", +tenant);
        return this.onGetWiseProperties(tenant)
                .flatMap(configuration -> cwWebClient.getRepository("time/entries",
                        WiseParamsUtils.mapToMultiValueMapBuild(queryParams))
                        .subscriberContext(ctx -> ctx.put("properties", configuration)));

    }

    public Flux<TimeEntry> getEntries(ClientProperties configuration) {
        log.debug("This tenant {} start sync connect wise time entry.", configuration.getTenantId());
        return this.loadRedisValue("sync-time-entries-" + configuration.getTenantId())
                .map(sysTime -> "lastUpdated > [" + sysTime + "]")
                .map(queryStr -> WiseParamsUtils.paginationBuild("1", queryStr))
                .flatMapMany(params -> this.cwWebClient.fetch("time/entries", params)
                        .switchMap(jsonNode -> {
                            if (ObjectUtils.isEmpty(jsonNode.get("id"))) {
                                log.error("This tenant sync get time entry error.msg: {}", jsonNode);
                                this.messagingTemplate.convertAndSend("exception.log", ExceptionLog.builder()
                                        .tenantId(configuration.getTenantId()).name("Connect wise")
                                        .status(500).type("SYNC-WISE-TIMES").msg("Connect wise sync times entry error.")
                                        .extend(jsonNode).build());
                                return Flux.empty();
                            }
                            return Flux.just(jsonNode);
                        }))
                .subscriberContext(ctx -> ctx.put("properties", configuration))
                .switchIfEmpty(Mono.error(new DataNotFoundException("This tenant " + configuration.getTenantId()
                        + " get entries is empty.")))
                .map(entriesNode -> WiseResultBuildUtils.buildTimeEntry(configuration.getTenantId(), entriesNode))
                .doOnNext(timeEntries -> this.loadRedisValue("sync-time-entries-" + configuration.getTenantId())
                        .subscribe(syncTime -> {
                            if (syncTime.isBefore(timeEntries.getUpdatedTime())) {
                                this.recordRedisValue("sync-time-entries-" + configuration.getTenantId(),
                                        timeEntries.getUpdatedTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
                            }
                        }));
    }


}
